import sys
import time
import plane_enemy
from plane_constant import *
from plane_hero import Hero
from plane_background import Background
from plane_sprites import *

class PlaneGame(object):
    """飞机大战主游戏"""

    def __init__(self):
        print("游戏初始化")

        clock.tick(FRAME_PER_SEC)

        #  设置定时器事件 - 创建敌机　1s
        pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
        pygame.time.set_timer(HERO_FIRE_EVENT, 500)

        #  调用私有方法，精灵和精灵组的创建
        self.__create_sprites()

    def __create_sprites(self):

        # 创建背景精灵和精灵组
        bg1 = Background()
        bg2 = Background(True)

        self.back_group = pygame.sprite.Group(bg1, bg2)

        # 创建敌机的精灵组
        self.enemy_group = pygame.sprite.Group()
        self.small_enemies = pygame.sprite.Group()
        self.__add_small_enemies(self.small_enemies, self.enemy_group, 15)
        self.mid_enemies = pygame.sprite.Group()
        self.__add_mid_enemies(self.mid_enemies, self.enemy_group, 4)
        self.big_enemies = pygame.sprite.Group()
        self.__add_big_enemies(self.big_enemies, self.enemy_group, 2)

        # 创建英雄的精灵和精灵组
        self.hero = Hero()
        self.hero_group = pygame.sprite.Group(self.hero)

    def start_game(self):
        print("游戏开始...")

        while True:
            #  事件监听
            self.__event_handler()


            #  碰撞检测
            self.__check_collide()

            #  更新/绘制精灵组
            self.__update_sprites()


            # 更新显示
            pygame.display.update()



    def __event_handler(self):

        for event in pygame.event.get():

            # 判断是否退出游戏
            if event.type == pygame.QUIT:
                self.__game_over()
            elif event.type == HERO_FIRE_EVENT:
                self.hero.fire()

        # 使用键盘提供的方法获取键盘按键 - SCREEN_RECT按键元组
        keys_pressed = pygame.key.get_pressed()
        # 判断元组中对应的按键索引值 1
        if keys_pressed[pygame.K_RIGHT]:
            self.hero.x_speed = 2
        elif keys_pressed[pygame.K_LEFT]:
            self.hero.x_speed = -2
        elif keys_pressed[pygame.K_UP]:
            self.hero.y_speed = -2
        elif keys_pressed[pygame.K_DOWN]:
            self.hero.y_speed = 2
        else:
            self.hero.x_speed = 0
            self.hero.y_speed = 0

    def __check_collide(self):
        global enemy_hit
        #判断是否游戏结束
        if self.hero.life_num == 0:
            # 结束游戏
            self.__game_over()
        else:
            # 1. 子弹摧毁敌机
            for b in self.hero.bullets:
                if b.active:
                    b.move()
                    enemy_hit = pygame.sprite.spritecollide(b,self.enemy_group,False,pygame.sprite.collide_mask)
                if  enemy_hit:
                    b.active = False
                    b.kill()
                    for e in  enemy_hit:
                        if e in self.enemy_group:
                            e.hit = True
                            e.energy -= 1
                            if e.energy == 0:
                                e.active = False
                        else:
                            e.active = False



            # 2. 敌机撞毁英雄
            enemies = pygame.sprite.spritecollide(self.hero,self.enemy_group,False,pygame.sprite.collide_mask)
            if enemies:
                # 撞毁英雄的敌机数不为0,要让英雄牺牲
                self.hero.active = False
                #让和英雄相撞的敌机死亡
                for e in enemies:
                    e.active = False



    def __update_sprites(self):

        global hero_destroy_index, e1_destroy_index,e2_destroy_index,e3_destroy_index
        global delay, switch_image, score


        #这里判断下游戏是否结束，未结束则需要绘制各种效果
        if self.hero.life_num:

            # 1.绘制喷气效果的英雄飞机
            if self.hero.active:
                if switch_image:
                    screen.blit(self.hero.image1, self.hero.rect)
                else:
                    screen.blit(self.hero.image2, self.hero.rect)

            else:
                if not (delay % 3):
                    # 绘制英雄飞机撞毁效果
                    screen.blit(self.hero.destroy_images[hero_destroy_index], self.hero.rect)
                    hero_destroy_index = (hero_destroy_index + 1) % 4
                    if hero_destroy_index == 0:
                        self.hero.life_num -= 1
                        self.hero.reset()

            # 2.绘制小型敌机
            for each in self.small_enemies:
                if each.active:
                    each.move()
                    screen.blit(each.image, each.rect)
                else:
                    # 毁灭
                    if not (delay % 5):
                        # if e1_destroy_index == 0:
                        # enemy1_down_sound.play()
                        screen.blit(each.destroy_images[e1_destroy_index], each.rect)
                        pygame.display.flip()
                        e1_destroy_index = (e1_destroy_index + 1) % 4
                        if e1_destroy_index == 0:
                            score += 1000
                            each.reset()


            #3.绘制中型敌机
            for each in self.mid_enemies:
                if each.active:
                    each.move()
                    if each.hit:
                        screen.blit(each.image_hit,each.rect)
                        each.hit = False
                    else:
                        screen.blit(each.image,each.rect)

                    #绘制血槽
                    pygame.draw.line(screen,BLACK,\
                                     (each.rect.left,each.rect.top - 5),\
                                     (each.rect.right,each.rect.top - 5),\
                                     2)
                    #print("{0},{1},{2}".format(each.rect.left,each.rect.top - 5,each.rect.right))
                    #当生命大于20%显示绿色，否则显示红色
                    energy_remain = each.energy / plane_enemy.MidEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen,energy_color,\
                                     (each.rect.left,each.rect.top - 5),\
                                     (each.rect.left + each.rect.width * energy_remain,each.rect.top - 5),\
                                     2)
                else:
                    #毁灭
                    if not (delay % 3):
                        screen.blit(each.destroy_images[e2_destroy_index],each.rect)
                        e2_destroy_index = (e2_destroy_index + 1) % 4
                        if e2_destroy_index == 0:
                            #enemy2_down_sound.play()
                            score += 6000
                            each.reset()
            # 4.绘制大型敌机
            for each in self.big_enemies:
                if each.active:
                    each.move()
                    if each.hit:
                        screen.blit(each.image_hit,each.rect)
                        each.hit = False
                    else:
                        if switch_image:
                            screen.blit(each.image,each.rect)
                        else:
                            screen.blit(each.image1,each.rect)
                    #绘制血槽
                    pygame.draw.line(screen,BLACK,\
                                     (each.rect.left,each.rect.top - 5),\
                                     (each.rect.right,each.rect.top - 5),\
                                     2)
                    #当生命大于20%显示绿色，否则显示红色
                    energy_remain = each.energy / plane_enemy.BigEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen,energy_color,\
                                     (each.rect.left,each.rect.top - 5),\
                                     (each.rect.left + each.rect.width * energy_remain,each.rect.top - 5),\
                                     2)
                    #即将出场，播放音效
                    if each.rect.bottom == -50:
                        #enemy3_fly_sound.play(-1)
                        pass
                else:
                    #毁灭
                    if not (delay % 3):
                        if e3_destroy_index == 0:
                            #enemy3_down_sound.play()
                            pass
                        screen.blit(each.destroy_images[e3_destroy_index],each.rect)
                        e3_destroy_index = (e3_destroy_index + 1) % 6
                        if e3_destroy_index == 0:
                            #enemy3_fly_sound.stop()
                            score += 10000
                            each.reset()


            # 5.绘制剩余生命数量
            for i in range(self.hero.life_num):
                   screen.blit(self.hero.life_image, (width - 10 - (i + 1) * self.hero.life_rect.width, height - 10 - self.hero.life_rect.height))

            pygame.display.flip()
            self.hero_group.update()
            self.hero_group.draw(screen)

            self.hero.bullets.draw(screen)

        pygame.display.flip()
        self.back_group.update()
        self.back_group.draw(screen)

        self.enemy_group.update()
        self.enemy_group.draw(screen)



        # 切换图片
        if not (delay % 5):
            switch_image = not switch_image
        delay -= 1
        if not delay:
            delay = 100
        # 增加延时，解决cup占用率较高的问题
        time.sleep(0.01)


    def __game_over(self):

        print("游戏结束")

        global recorded  #引用类为全局变量需要额外声明

        if not recorded:
            recorded = True
            # 读取历史最高得分
            with open("record.txt", "r") as f:
                record_score = int(f.read())
            # 如果玩家得分高于历史最高得分，则存档
            if score > record_score:
                with open("record.txt", "w") as f:
                    f.write(str(score))

        #绘制游戏结束画面
        gameover_text1 = gameover_font.render("Your Score", True, (255, 255, 255))
        gameover_text1_rect = gameover_text1.get_rect()
        gameover_text1_rect.left, gameover_text1_rect.top = (width - gameover_text1_rect.width) // 2, \
                                                            (height - gameover_text1_rect.height) // 2 - 50
        screen.blit(gameover_text1, gameover_text1_rect)

        gameover_text2 = gameover_font.render(str(score), True, (255, 255, 255))
        gameover_text2_rect = gameover_text2.get_rect()
        gameover_text2_rect.left, gameover_text2_rect.top = (width - gameover_text2_rect.width) // 2, \
                                                            gameover_text1_rect.bottom + 10

        screen.blit(gameover_text2, gameover_text2_rect)

        restart_rect.left, restart_rect.top = (width - restart_rect.width) // 2, (gameover_text2_rect.bottom + 50)
        screen.blit(restart_image, restart_rect)

        quit_rect.left, quit_rect.top = (width - quit_rect.width) // 2, restart_rect.bottom + 10
        screen.blit(quit_image, quit_rect)
        pygame.display.flip()

        # 检测用户的鼠标操作
        # 如果用户按下鼠标左键
        if pygame.mouse.get_pressed()[0]:
            # 获取鼠标坐标
            pos = pygame.mouse.get_pos()
            # 如果用户点击“重新开始，重新开始游戏”
            if restart_rect.left < pos[0] < restart_rect.right and restart_rect.top < pos[1] < restart_rect.bottom:
                # 调用main()函数，重新开始游戏
                main()
            # 如果用户点击“结束游戏”
            elif quit_rect.left < pos[0] < quit_rect.right and quit_rect.top < pos[1] < quit_rect.bottom:
                pygame.quit()
                sys.exit()


    def __add_small_enemies(self,group1,group2,num):
        for i in range(num):
            e1 = plane_enemy.SmallEnemy(bg_size)
            group1.add(e1)
            group2.add(e1)

    def __add_mid_enemies(self,group1, group2, num):
        for i in range(num):
            e2 = plane_enemy.MidEnemy(bg_size)
            group1.add(e2)
            group2.add(e2)

    def __add_big_enemies(self,group1, group2, num):
        for i in range(num):
            e3 =  plane_enemy.BigEnemy(bg_size)
            group1.add(e3)
            group2.add(e3)

def main():
    # 创建游戏对象
    game = PlaneGame()
    # 启动游戏
    game.start_game()

if __name__ == '__main__':
    main()



